package org.yelongframework.model.generator.pdm;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;
import org.yelongframework.core.pair.Pair;
import org.yelongframework.model.generator.manager.DefaultGenFieldAndColumn;
import org.yelongframework.model.generator.manager.DefaultGenModelAndTable;
import org.yelongframework.model.generator.manager.GenFieldAndColumn;
import org.yelongframework.model.generator.manager.GenModelAndTable;
import org.yelongframework.pdm.PdmColumn;
import org.yelongframework.pdm.PdmResolveException;
import org.yelongframework.pdm.PdmResolver;
import org.yelongframework.pdm.PdmTable;

/**
 * 默认实现
 * 
 * @since 1.0.0
 */
public class DefaultModelGeneratePdmResolver implements ModelGeneratePdmResolver {

	/** PDM解析器 */
	private final PdmResolver pdmResolver;

	// ==================================================构造器==================================================

	/**
	 * @param pdmResolver PDM解析器
	 */
	public DefaultModelGeneratePdmResolver(PdmResolver pdmResolver) {
		this.pdmResolver = Objects.requireNonNull(pdmResolver, "pdmResolver");
	}

	// ==================================================解析==================================================

	@Override
	public List<GenModelAndTable> resolve(InputStream inputStream) throws PdmResolveException, IOException {
		List<PdmTable> pdmTables = pdmResolver.resolveTables(inputStream);
		List<GenModelAndTable> genModelAndTableList = new ArrayList<>();
		for (PdmTable pdmTable : pdmTables) {
			genModelAndTableList.add(buildGenModelAndTable(pdmTable));
		}
		return genModelAndTableList;
	}

	// ==================================================构建模型表==================================================

	/**
	 * 构建生成模型表
	 * 
	 * @param pdmTable PDM表
	 * @return 生成模型表
	 */
	protected GenModelAndTable buildGenModelAndTable(PdmTable pdmTable) {
		List<PdmColumn> columns = pdmTable.getColumns();
		List<GenFieldAndColumn> genFieldAndColumns = columns.stream().map(this::buildGenFieldAndColumn)
				.collect(Collectors.toList());
		DefaultGenModelAndTable genModelAndTable = new DefaultGenModelAndTable(pdmTable.getComment(),
				pdmTable.getCode(), genFieldAndColumns);
		genModelAndTable.setTableDesc(pdmTable.getName());
		return genModelAndTable;
	}

	// ==================================================构建字段列==================================================

	/**
	 * 构建生成字段列
	 * 
	 * @param pdmColumn PDM列
	 * @return 生成字段列
	 */
	protected GenFieldAndColumn buildGenFieldAndColumn(PdmColumn pdmColumn) {
		Pair<String, Class<?>> dataTypePair = resolveDataType(pdmColumn.getDataType());
		DefaultGenFieldAndColumn genFieldAndColumn = new DefaultGenFieldAndColumn(pdmColumn.getCode(),
				pdmColumn.getCode(), dataTypePair.getRight());
		genFieldAndColumn.setDesc(pdmColumn.getComment());
		genFieldAndColumn.setColumnName(pdmColumn.getName());
		genFieldAndColumn.setJdbcType(dataTypePair.getLeft());
		genFieldAndColumn.setMaxLength(pdmColumn.getLength());
		genFieldAndColumn.setAllowNull(StringUtils.isNotBlank(pdmColumn.getModifier()));
		return genFieldAndColumn;
	}

	// ==================================================数据类型==================================================

	/**
	 * 解析数据类型
	 * 
	 * @param dataType 数据类型
	 * @return 数据类型对
	 */
	protected Pair<String, Class<?>> resolveDataType(String dataType) {
		Class<?> fieldType = null;
		String columnType = "";
		dataType = dataType.toUpperCase();
		if (dataType.contains("INTEGER")) {
			fieldType = Integer.class;
			columnType = "INTEGER";
		} else if (dataType.contains("FLOAT")) {
			fieldType = Float.class;
			columnType = "FLOAT";
		} else if ((dataType.contains("NUMBER")) || (dataType.contains("NUMERIC")) || (dataType.contains("DECIMAL"))) {
			fieldType = Double.class;
			columnType = "NUMBER";
		} else if ((dataType.contains("DATE")) || (dataType.contains("TIMESTAMP"))) {
			fieldType = Date.class;
			columnType = "TIMESTAMP";
		} else {
			fieldType = String.class;
			columnType = "VARCHAR";
		}
		return new Pair<>(columnType, fieldType);
	}

	// ==================================================PDM解析器==================================================
	@Override
	public PdmResolver getPdmResolver() {
		return pdmResolver;
	}

}
